package com.questetra.bpms.android;

import java.io.IOException;

import org.apache.http.client.protocol.RequestAddCookies;
import org.apache.http.client.protocol.ResponseProcessCookies;
import org.apache.http.impl.client.DefaultHttpClient;

import android.content.Context;

import com.google.api.client.apache.ApacheHttpTransport;
import com.google.api.client.auth.oauth.OAuthAuthorizeTemporaryTokenUrl;
import com.google.api.client.auth.oauth.OAuthCallbackUrl;
import com.google.api.client.auth.oauth.OAuthCredentialsResponse;
import com.google.api.client.auth.oauth.OAuthGetAccessToken;
import com.google.api.client.auth.oauth.OAuthGetTemporaryToken;
import com.google.api.client.auth.oauth.OAuthHmacSigner;
import com.google.api.client.auth.oauth.OAuthParameters;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpTransport;
import com.questetra.bpms.android.Preferences.NotFoundException;

public class OAuthService {
    public static final String CONSUMER_KEY = "com.questetra.bpms.android";

    private String qbpmsUrl = null;
    private String consumerKey = null;
    private String consumerSecret = null;

    private HttpTransport transport = new HttpTransport();

    private static OAuthService service = new OAuthService();
    private OAuthHmacSigner signer;

    private OAuthService() {
        HttpTransport.setLowLevelHttpTransport(ApacheHttpTransport.INSTANCE);
        DefaultHttpClient httpClient = (DefaultHttpClient) ApacheHttpTransport.INSTANCE.httpClient;
        httpClient.removeRequestInterceptorByClass(RequestAddCookies.class);
        httpClient.removeResponseInterceptorByClass(ResponseProcessCookies.class);
        //HttpParams params = new BasicHttpParams();
        //params.setParameter("http.protocol.handle-redirects", true);
        //httpClient.setParams(params);
        signer = new OAuthHmacSigner();
    }

    public static OAuthService getInstance() {
        return service;
    }

    public synchronized void setup(Context context) throws NoSettingsException,
            NoAccessTokenException {
        try {
            QbpmsInfo info = Preferences.getQbpmsInfo(context);
            this.qbpmsUrl = "https://" + info.host + ".questetra.net/"
                    + info.path;
            this.consumerKey = CONSUMER_KEY;
            this.consumerSecret = info.consumerSecret;
        } catch (NotFoundException e) {
            throw new NoSettingsException();
        }

        try {
            OAuthCredentialsResponse credentials = Preferences.getToken(context);
            setupAccessToken(credentials.token, credentials.tokenSecret);
        } catch (NotFoundException e) {
            throw new NoAccessTokenException();
        }
    }

    public synchronized void reset(Context context, QbpmsInfo info) {
        Preferences.putQbpmsInfo(context, info);
        StatsWidgetProvider.StatsService.reset(context);
    }

    public OAuthCredentialsResponse getUnauthorizedRequestToken()
            throws IOException {
        if (qbpmsUrl == null) {
            throw new IOException("not QBPMS URL settings");
        }
        OAuthGetTemporaryToken get = new OAuthGetTemporaryToken(qbpmsUrl
                + "/OAuth/requestToken");
        get.callback = "qbpms://android";
        get.consumerKey = this.consumerKey;
        signer.clientSharedSecret = consumerSecret;
        signer.tokenSharedSecret = null;
        get.signer = signer;
        OAuthCredentialsResponse response = get.execute();
        signer.tokenSharedSecret = response.tokenSecret;
        return response;
    }

    public String getAuthorizeUrl(String token) {
        OAuthAuthorizeTemporaryTokenUrl authorizationUrl = new OAuthAuthorizeTemporaryTokenUrl(qbpmsUrl
                + "/OAuth/confirmAccess");
        authorizationUrl.temporaryToken = token;

        return authorizationUrl.build();

    }

    public String getAuthorizedUrl() {
        return qbpmsUrl + "/OAuth/authorized";
    }

    public void getAccessToken(String callbackUrl, Context context)
            throws IOException {
        if (qbpmsUrl == null) {
            throw new IOException("not QBPMS URL settings");
        }
        OAuthCallbackUrl callback = new OAuthCallbackUrl(callbackUrl);
        OAuthGetAccessToken request = new OAuthGetAccessToken(qbpmsUrl
                + "/OAuth/accessToken");
        request.temporaryToken = callback.token;
        request.verifier = callback.verifier;
        request.consumerKey = this.consumerKey;
        signer.clientSharedSecret = this.consumerSecret;
        request.signer = signer;
        OAuthCredentialsResponse response = request.execute();

        Preferences.putToken(context, response);

        setupAccessToken(response.token, response.tokenSecret);
    }

    private void setupAccessToken(String token, String tokenSharedSecret) {
        OAuthParameters parameters = new OAuthParameters();
        parameters.consumerKey = this.consumerKey;
        signer.clientSharedSecret = this.consumerSecret;
        signer.tokenSharedSecret = tokenSharedSecret;
        parameters.signer = signer;
        parameters.token = token;
        parameters.signRequestsUsingAuthorizationHeader(transport);
    }

    public synchronized String getResponse(String url) throws IOException {
        if (qbpmsUrl == null) {
            throw new IOException("not QBPMS URL settings");
        }
        HttpRequest request = transport.buildGetRequest();
        request.setUrl(qbpmsUrl + url);
        HttpResponse response = request.execute();
        return response.parseAsString();
    }

    public String getQbpmsUrl() {
        return qbpmsUrl;
    }
}
